package com.ohuang.apkMerge

import java.io.File
import java.io.FileReader
import java.io.FileWriter
import java.lang.StringBuilder
import java.util.LinkedList
import java.util.TreeMap
import java.util.TreeSet

fun findSmaliInClass(rootPath: String, path: String): ArrayList<String> {
    val arrayList = ArrayList<String>()
    var file = File(rootPath)
    file.listFiles()?.forEach {
        if (it.isDirectory) {
            var file1 = File(it.absolutePath + "/" + path)
            if (file1.exists()) {
                println(file1.absolutePath)
                arrayList.add(file1.absolutePath)
            }

        }
    }

    return arrayList
}

/**
 * 获取R.smali下的字段名称
 */
fun getRSmaliFieldName(path: String):List<String>{
    val fileReader = FileReader(path)
    val linkedList=LinkedList<String>()
    val readLines = fileReader.readLines()
    readLines.forEach {
        if (it.startsWith(".field public static final")) {
            val s = StringBuilder().append(it).toString().replace(".field public static final", "")
            val split = s.split(":I =")
            if (split.size != 2) {
                return@forEach
            }
            val name = split[0].replace(" ", "")
            if (name.isNotEmpty()){
                linkedList.add(name)
            }
        }
    }

    fileReader.close()
    return linkedList
}

/**
 * 改变R.smali的值
 */
fun changeRSmali(path: String, map: HashMap<String, String>) {

    var fileReader = FileReader(path)

    var sb = StringBuilder()


    var readLines = fileReader.readLines()
    readLines.forEach {
        if (it.startsWith(".field public static final")) {
            var s = StringBuilder().append(it).toString().replace(".field public static final", "")
            var split = s.split(":I =")
            if (split.size != 2) {
                sb.append(it)
                sb.append("\n")
                return@forEach
            }
            var name = split[0].replace(" ", "")
            if (map.containsKey(name)) {
                var id = map[name]
                if (id != null && id!!.isNotEmpty()) {
                    var sp = StringBuilder().append(it).toString().replace(split[1].replace(" ", ""), id)
                    sb.append(sp)
                } else {
                    sb.append(it)
                }
            } else {
                sb.append(it)
            }

        } else {
            sb.append(it)
        }
        sb.append("\n")
    }


    var fileWriter = FileWriter(path)
    // 把替换完成的字符串写入文件内
    fileWriter.write(sb.toString().toCharArray());
    // 关闭文件流，释放资源
    fileReader.close()
    fileWriter.close()

}

fun copySmaliAndUpdaterSmali(path: String, path1: String, public: String) {
    var copySmali = copySmaliClass(path, path1)
    updateRSmali(public, copySmali)
}

fun updateRSmali(public: String, smaliList: MutableList<String>) {
    var readPublic = readPublic(public)

    val data = ArrayList<String>()

    smaliList.forEach {
        searchFileInPath(it, "R.smali", data)
    }

    data.forEach { itS ->
        println("----开始修改" + itS + "-----")
        var file1 = File(itS)
        var parentFile = file1.parentFile
        parentFile.listFiles()?.forEach { itF ->
            if (itF.isFile) {
                if (itF.name.startsWith("R\$")) {
                    var name = StringBuilder().append(itF.name).toString()
                    var key = name.replace("R\$", "").replace(".smali", "")
                    var hashMap = readPublic[key]
                    if (hashMap != null) {
                        changeRSmali(itF.absolutePath, hashMap)
                    }
                }
            }
        }
    }
}


/**
 * 修改public.xml 后更新R.smali
 */
fun updateRSmali2(public: String, path: String) {
    var readPublic = readPublic(public)
    var file = File(path)
    val data = ArrayList<String>()

    if (file.isDirectory) {
        searchFileInPath(file.absolutePath, "R.smali", data)
    } else if ("R.smali" == file.name) {
        data.add(file.absolutePath)
    }

    data.forEach { itS ->
        println("----开始修改" + itS + "-----")
        var file1 = File(itS)
        var parentFile = file1.parentFile
        parentFile.listFiles()?.forEach { itF ->
            if (itF.isFile) {
                if (itF.name.startsWith("R\$")) {
                    var name = StringBuilder().append(itF.name).toString()
                    var key = name.replace("R\$", "").replace(".smali", "")
                    var hashMap = readPublic[key]
                    if (hashMap != null) {
                        changeRSmali(itF.absolutePath, hashMap)
                    }
                }
            }
        }
    }
}

/**
 * 复制smali
 */
fun copySmaliClass(path: String, path1: String): MutableList<String> {
    var file = File(path)
    var file1 = File(path1)
    var index = 1
    file1.listFiles()?.forEach {
        if (it.isDirectory) {
            if (it.name.startsWith("smali_classes")) {
                var string = StringBuffer().append(it.name).toString().replace("smali_classes", "")
                var i = string.toInt()
                if (i > index) {
                    index = i
                }
            }
        }
    }
    var data = ArrayList<String>()
    val smaliPath = "$path1\\smali_classes"
    var smaliFile = File("$path\\smali")
    if (smaliFile.exists()) {
        index++
        println("------开始复制${smaliFile.name}到smali_classes" + index + "------")
        copyPathAllFile(smaliFile.absolutePath, smaliPath + index)
        data.add(smaliPath + index)
    }
    var p = 1
    while (true) {
        p++
        smaliFile = File("$path\\smali_classes$p")
        if (smaliFile.exists()) {
            index++
            println("------开始复制${smaliFile.name}到smali_classes" + index + "------")
            copyPathAllFile(smaliFile.absolutePath, smaliPath + index)
            data.add(smaliPath + index)
        } else {
            break
        }
    }
    return data
}


/**
 * 复制smali并替换一些包名  并进行包名替换(用于解决第三方库冲突问题)
 *
 * replaceMap  替换规则 key为原包名  value为修改后的包名
 */
fun copyAndChangePackageName(path: String, path1: String, replaceMap: Map<String, String>) {
    var file = File(path)
    var file1 = File(path1)

    file.listFiles()?.forEach {
        if (it.isDirectory) {

            if (it.name.startsWith("smali")) {
                println("------开始复制${it.name} ------")
                copyAndChangePnSmali(it.absolutePath, path1 + "/" + it.name, replaceMap = replaceMap)
            }
        }

    }


}

/**
 * 复制+替换包名
 */
fun copyAndChangePnSmali(
    sourceRootPath: String,
    targetRootPath: String,
    path: String = "",
    path1: String = "",
    replaceMap: Map<String, String>

) {
    var targetFile = File(targetRootPath + path1)
    var sourceRootFile = File(sourceRootPath + path)
    if (!targetFile.exists()) {
        targetFile.mkdirs()
    }
    sourceRootFile.listFiles()?.forEach {
        if (it.isDirectory) {
            var newPath0 = path + "/${it.name}"
            val newPath2 = path1 + "/${it.name}"
            val key=newPath2.subSequence(1,newPath2.length)
            if (replaceMap.containsKey(key)) {
                val newPath2 = newPath2.replace(key.toString(), replaceMap[key]!!)
                println("$key->${replaceMap[key]}")
                copyAndChangePnSmali(sourceRootPath, targetRootPath, newPath0, newPath2, replaceMap)
            } else {
                copyAndChangePnSmali(sourceRootPath, targetRootPath, newPath0, newPath2, replaceMap)
            }

        } else {
            copyAndChangeSmaliFile(it.absolutePath, targetRootPath + path1 + "/" + it.name, replaceMap)
        }
    }
}

/**
 *  内容替换
 */
fun copyAndChangeSmaliFile(sourcePath: String, targetPath: String, replaceMap: Map<String, String>) {
    var fileReader = FileReader(sourcePath)

    var sb = StringBuilder()


    var readLines = fileReader.readLines()
    readLines.forEach {
        var stringBuilder = StringBuilder(it)
        replaceMap.forEach { (t, u) ->
            var replace = stringBuilder.toString().replace(t, u)
            stringBuilder = StringBuilder(replace)
        }
        sb.append(stringBuilder).append("\n")

    }


    var fileWriter = FileWriter(targetPath)
    // 把替换完成的字符串写入文件内
    fileWriter.write(sb.toString().toCharArray());
    // 关闭文件流，释放资源
    fileReader.close()
    fileWriter.close()
}

/**
 * 根据R.smali生成R.txt
 */
fun generateRTxt(path: String,RTxtPath:String){
    val hashMap = findResNameMap(path)
    val file1 = File(RTxtPath)
    if (file1.parentFile!=null){
        file1.parentFile.mkdirs()
    }
    val fileWriter = FileWriter(file1)
    hashMap.forEach {
        val key = it.key
        it.value.forEach {name->
            fileWriter.write("int ${key} ${name} 0x0\n")
        }
    }
    fileWriter.close()
}

/**
 *   map<type,names>
 *
 */
 fun findResNameMap(path: String): TreeMap<String, MutableSet<String>> {
    val file = File(path)
    val data = ArrayList<String>()
    if (file.isDirectory) {
        searchFileInPath(file.absolutePath, "R.smali", data)
    } else if ("R.smali" == file.name) {
        data.add(file.absolutePath)
    }
    val hashMap = TreeMap<String, MutableSet<String>>()

    data.forEach { itS ->
        println("----开始查找$itS-----")
        val file1 = File(itS)
        val parentFile = file1.parentFile
        parentFile.listFiles()?.forEach { itF ->
            if (itF.isFile) {
                if (itF.name.startsWith("R\$")) {
                    val type = itF.name.replace(".smali", "").replace("R\$", "")

                    var set: MutableSet<String> = TreeSet()
                    if (hashMap.containsKey(type)) {
                        set = hashMap[type]!!
                    } else {
                        hashMap[type] = set
                    }
                    val rSmaliFieldName = getRSmaliFieldName(itF.absolutePath)
                    set.addAll(rSmaliFieldName)
                }
            }
        }
    }
    return hashMap
}


/**
 * 删除R.smali
 */
fun deleteRSmali(path: String) {

    var file = File(path)
    val data = ArrayList<String>()

    if (file.isDirectory) {
        searchFileInPath(file.absolutePath, "R.smali", data)
    } else if ("R.smali" == file.name) {
        data.add(file.absolutePath)
    }

    data.forEach { itS ->
        println("----开始删除$itS-----")
        var file1 = File(itS)
        var parentFile = file1.parentFile
        parentFile.listFiles()?.forEach { itF ->
            if (itF.isFile) {
                if (itF.name.startsWith("R\$")) {
                    var delete = itF.delete()
                    if (delete) {
                        println("删除文件" + itF.absolutePath)
                    } else {
                        println("删除文件失败" + itF.absolutePath)
                    }
                } else if (itF.name.equals("R.smali")) {
                    var delete = itF.delete()
                    if (delete) {
                        println("删除文件" + itF.absolutePath)
                    } else {
                        println("删除文件失败" + itF.absolutePath)
                    }
                }
            }
        }
    }
}
